import json
import os
import re
from time import sleep
import func_timeout
from func_timeout import func_set_timeout

connection = []  # 存储的是bitcoin-cli getpeerinfo命令获得的邻居集合
ip_from_getaddr = []  # 存储的是connection和getaddr获得的地址ip
ip_from_getaddr_quchong = []


def get_init_peerinfo():
    os.system('bitcoind')
    sleep(3)  # 刚启动的客户端需要时间来连接节点
    r = os.popen('bitcoin-cli getpeerinfo')
    peer_list = json.load(r)
    with open('/root/src/bcclient/data/peers.txt', 'w', encoding='utf8') as wp:
        for index, addr in enumerate(peer_list):
            ip_and_port = addr['addr']
            if '[' not in ip_and_port:  # 没有[]的是ipv4地址
                ipv4 = ip_and_port.split(":")
                ip = ipv4[0]
                port = ipv4[1]
                connection.append({'ip': ip, 'port': port})
                res = ip + ' ' + port + '\n'
                wp.writelines(res)
    print(len(peer_list))
    return connection


def get_ip_getaddr():
    """
        定时获取getaddr消息的返回值
        """
    print("开始获取getaddr返回的地址消息")

    os.system(
        'cd /root/src/bcclient/ && ./bcclient -s getaddr -l addr -l idle --tries 2 --delay 10 -f data/peers.txt  -o data/getaddrlist.out')


def listen_source_flie():
    """
        生成用于bcclient监听的目标地址集合
        """
    path_bcclient = '/root/src/bcclient/data/'
    os.system('rm -rf ' + path_bcclient + 'source.txt')
    os.system('cd  ' + path_bcclient + ' && cp peers.txt source.txt ')
    with open(path_bcclient + 'getaddrlist.out', 'r', encoding='utf8') as fp:
        for line in fp.readlines():
            if " r:addr:" in line:
                '''
                                需要检查，目前的情况是使用bcclient的命令参数输出日志文件会出现记录不全的情况
                                导致下面进行字符串子串检索时失败
                                如果使用linux 的>>的重定向，情况未知 
                                '''
                try:
                    information = line.split("r:addr:")
                    ipinformation = information[1]  # 203.159.5.131,18333,1640398794,175.41.186.215:18333.2
                    temp = ipinformation.split(',')  # list类型
                    if len(temp) == 4:
                        li = re.findall(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", temp[0])
                        if len(li) == 0:
                            continue
                        ip_str = li[0]

                        li = re.findall(r"\b[0-9]{4,5}", temp[1])
                        if len(li) == 0:
                            continue
                        port = li[0]
                        if '.' in ip_str and port != "":  # ipv4
                            ip_from_getaddr.append({'ip': ip_str, 'port': port})
                except IndexError:
                    continue

    print("未处理addr个数：" + str(len(ip_from_getaddr)))
    ip_quchong = quchong(ip_from_getaddr)
    print("处理后的addr个数：" + str(len(ip_quchong)))
    with open(path_bcclient + 'source.txt', 'a+', encoding='utf8') as wp:
        for dict in ip_quchong:
            ip = dict['ip']
            port = dict['port']
            wp.writelines(ip + " " + port + "\n")


def addr_weight():
    """
        记录所有节点的在线权重，初始为0，每成功连接一次+1，timeout一次-1，范围【-5，5】
        :return:
        """
    pass
    # 这个功能需要跑在监听结束之后才行


def quchong(source_list):
    """
        list set互转的去重方式只适用于普通列表，不支持[{字典}，{}]
        :return:去重后的列表
        """
    new_list = []
    seen = set()
    for d in source_list:
        t = tuple(d.items())
        if t not in seen:
            seen.add(t)
            new_list.append(d)
    return new_list


def listen():
    """
        监听函数，未来考虑设置成多进程的方式
        """
    os.system(
        'cd /root/src/bcclient/ && ./bcclient -l tx -l inv -l addr -l idle --tries 3 -f data/source.txt -n 3 -o data/listen0109.txt')
    os.system("./bcclient -l tx -l inv -idle -p 18333  108.59.197.192")
    os.system("""

    curl -s -X POST --user zjz:123456 -H 'content-type: text/plain;' http://127.0.0.1:8332/ --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getconnectioncount", "params": [] }'

    """)


if __name__ == '__main__':
    print("获取bitcoin邻居地址：")
    get_init_peerinfo()
    print("删除之前的输出文件")
    os.system('cd /root/src/bcclient/data && rm -rf getaddrlist.out')
    print("删除之前的输出文件")
    get_ip_getaddr()
    sleep(10)
    print("完成")
    os.system('killall bcclient')  # 函数停止了，但是bcclient进程还在
    print('bcclient发送getaddr消息完成,生成文件getaddrlist.out')

    listen_source_flie()
    # 监听
    print("删除上一次的监听文件")
    print("监听可以开始")
    # os.system("cd /root/src/bcclient/data/ && rm -rf listen.out")

